package com.winiex.datastructure;

import com.winiex.datastructure.exception.QueueEmptyException;

public class LinkQueue<T> implements Queue<T>{
	
	private Node<T> front;
	private Node<T> rear;
	private int length;
	
	/**
	 * Initialize a LinkQueue.
	 */
	public LinkQueue() {
		Node<T> head = new Node<T>();
		rear = front = head;
		length = 0;
	}
	
	
	@Override
	public void ClearQueue() {
		rear = front;
		length = 0;
	}

	@Override
	public boolean QueueEmpty() {
		return length == 0;
	}

	@Override
	public int QueueLength() {
		return length;
	}

	@Override
	public T GetHead() {
		if (front.next == null) {
			return null;
		}
		
		return front.next.elem;
	}

	@Override
	public void EnQueue(T node) {
		Node<T> newNode = new Node<T>();
		newNode.elem = node;
		newNode.next = null;
		
		rear.next = newNode;
		rear = rear.next;
		length ++;
	}

	@Override
	public T DeQueue() throws QueueEmptyException {
		if (front == rear) {
			throw new QueueEmptyException("The LinkQueue is Empty. Can't DeQueue.");
		}
		
		Node<T> node = front.next;
		front = front.next;
		length --;
		
		return node.elem;
	}

	@Override
	public void QueueTraverse(Traverse<T> t) {
		if (length ==0) {
			return;
		}
		
		for (Node<T> iter = front.next ; iter != null ; iter = iter.next) {
			t.traverse(iter.elem);
		}
	}
	
	private class Node<N> {
		T elem;
		Node<N> next;
		
		Node() {
			this(null);
		}
		
		Node(T elem) {
			this.elem = elem;
			this.next = null;
		}
	}
	
	public static class DefaultLinkQueueTraverse<T> implements Traverse<T> {

		@Override
		public void traverse(T t) {
			System.out.println(t.toString());
		}
		
	}
	
}
